package org.pro.Model;

import java.io.*;
import java.util.*;

import org.pro.utils.Utils;


import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

public class WarData  implements Serializable{
    public CopyOnWriteArrayList<Element> elements = new CopyOnWriteArrayList<>();
    public static final long serialVersionUID = 6L;
  // public ConcurrentLinkedQueue<Element> elements = new ConcurrentLinkedQueue<>();
    public Tank userTank;
    public Tank enemyTank;
    public long startTime;//开始时间么
    public long pausedTime = 0; // 添加暂停时间
    public int demagetanks =0;
    public static final String SAVE_DIR = "saves";
    //尝试网格碰撞检测
    public Map<String, List<Element>> spatialGrid = new HashMap<>();
    public static final int GRID_SIZE = 50; // 网格大小为100x100

    public WarData() {
        //600 ，200
        this.AddGrosss();
        this.AddRivers();
        this.userTank = new Tank(200, 300, 0.0, 110.0, 1, TankTeam.RED.ordinal());
        this.enemyTank=new Tank(400, 500, 0.0, 110.0, 1, TankTeam.BLUE.ordinal());
        this.elements.add(this.userTank);
        this.elements.add(this.enemyTank);
        this.startTime = System.currentTimeMillis();//获取运行游戏的时间么？
    }

    public void updatePositions(double timeFlaps) {
        Iterator var3 = this.elements.iterator();
        while(var3.hasNext()) {
            Element elemnet = (Element)var3.next();
            if(elemnet instanceof Tank) {
                Tank t = (Tank)elemnet;
                t.update(timeFlaps,this.elements);
            }
            else
                elemnet.update(timeFlaps);
        }

    }

    public void updateDataSet() {
        // 收集需要移除的元素
        List<Element> elementsToRemove = new ArrayList<>();
        for (Element tmp : this.elements) {
            if (tmp.Destroyed && tmp != this.userTank) {
                elementsToRemove.add(tmp);
            }
        }
        // 统一移除
        for (Element element : elementsToRemove) {
            this.elements.remove(element);
        }
    }


    // 修改获取已过去时间的方法
    public long getElapsedTime() {
        return System.currentTimeMillis() - startTime - pausedTime;
    }

    //增加数量咯
    public void increaseDemagetanks() {
        this.demagetanks++;
    }
    //获取摧毁的坦克数
    public int getdestroytanks() {
        return this.demagetanks;
    }
    //存档
    public void saveGame(String filename) throws IOException {
        File dir = new File(SAVE_DIR);
        if (!dir.exists()) dir.mkdirs();

        String fullPath = SAVE_DIR + File.separator + filename;
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fullPath))) {
            // 保存关键状态
            Map<String, Object> gameState = new HashMap<>();
           gameState.put("elements", this.elements);
           gameState.put("userTank", this.userTank);
            long elapsedTime = getElapsedTime(); // 直接获取已运行时间
            gameState.put("elapsedTime", elapsedTime); // 新增字段
            gameState.put("startTime", this.startTime);
            gameState.put("pausedTime", this.pausedTime);
           gameState.put("demagetanks", this.demagetanks);
           System.out.printf("save_start_time: %d\n", this.startTime);
           System.out.printf("save_paused_time: %d\n", this.pausedTime);
            oos.writeObject(gameState);
        }
    }

    public static WarData loadGame(String filename) throws IOException, ClassNotFoundException {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
            WarData warData = new WarData(); // 创建新实例
            Map<String, Object> gameState = (HashMap<String, Object>) ois.readObject();

            // 恢复状态
            warData.elements = (CopyOnWriteArrayList<Element>) gameState.get("elements");
            warData.userTank = (Tank) gameState.get("userTank");
            warData.demagetanks = (int) gameState.get("demagetanks");
            // 获取存档时的原始时间数据
            long savedElapsedTime = (long) gameState.get("elapsedTime"); // 读取已运行时间
            // 重置时间参数
            warData.startTime = System.currentTimeMillis() - savedElapsedTime;
            warData.pausedTime = 0; // 加载后未暂停
            return warData;
        }
    }
    //添加一个河流
    public void AddRiver(int x, int y) {
        River t = new River(x, y);
        this.elements.add(t);
    }
    public void AddGross(int x,int y)
    {
        Gross t=new Gross(x,y);
        this.elements.add(t);
    }

    //添加河流
    public void AddRivers()
    {
        //横着加2
        //竖着一个
        int[] x=new int[3];
        int[] y=new int[3];
        int posx=595;
        int posy=120;
        x[0]=0;
        x[1]=42;
        x[2]=0;
        y[0]=0;
        y[1]=0;
        y[2]=-34;
        for(int i=0;i<3;i++)
        {
            int px=posx+x[i];
            int py=posy+y[i];
            AddRiver(px,py);
        }
        posx=280;
        posy=120;
        x[1]=-x[1];
        for(int i=0;i<3;i++)
        {
            int px=posx+x[i];
            int py=posy+y[i];
            AddRiver(px,py);
        }
        posx=280;
        posy=400;
        y[2]=-y[2];
        for(int i=0;i<3;i++)
        {
            int px=posx+x[i];
            int py=posy+y[i];
            AddRiver(px,py);
        }
        posx=595;
        posy=400;
        x[1]=-x[1];
        for(int i=0;i<3;i++)
        {
            int px=posx+x[i];
            int py=posy+y[i];
            AddRiver(px,py);
        }
        //竖着加5个
    }
    //添加草丛
    public void AddGrosss()
    {
        int beginx=325;
        int endx=600;
        int beginy=153;
        int endy=400;
        int dx=45;
        int dy=32;
        for(beginx=325;beginx<570;beginx=beginx+dx)
            AddGross(beginx,beginy);
        beginx=325;
       for(beginy=153;beginy<349;beginy=beginy+dy)
            AddGross(beginx,beginy+dy);
       beginx=550;
        for(beginy=153;beginy<349;beginy=beginy+dy)
            AddGross(beginx,beginy+dy);
        beginy=377;
        for(beginx=373;beginx<540;beginx=beginx+dx)
            AddGross(beginx,beginy);
    }

    // 获取草丛列表
    public CopyOnWriteArrayList<Gross> getGrossList() {
        CopyOnWriteArrayList<Gross> grossList = new CopyOnWriteArrayList<>();
        for (Element e : elements) {
            if (e instanceof Gross) {
                grossList.add((Gross)e);
            }
        }
        return grossList;
    }

    /// 更新元素到网格
    public void updateSpatialGrid() {
        spatialGrid.clear();
        for (Element e : elements) {
            int gridX = (int)(e.x / GRID_SIZE);
            int gridY = (int)(e.y / GRID_SIZE);
            String key = gridX + "," + gridY;
            spatialGrid.computeIfAbsent(key, k -> new ArrayList<>()).add(e);
        }
    }
    public void CollisionDetection() {
        updateSpatialGrid(); // 更新空间网格

        // 只遍历坦克对象（而非所有元素）
        for (Element tank : elements) {
            if (!(tank instanceof Tank)) continue; // 仅处理坦克
            Tank t = (Tank) tank;

            // 获取坦克所在网格及相邻网格
            int gridX = (int)(t.x / GRID_SIZE);
            int gridY = (int)(t.y / GRID_SIZE);

            // 遍历3x3相邻网格
            for (int dx = -1; dx <= 1; dx++) {
                for (int dy = -1; dy <= 1; dy++) {
                    String key = (gridX + dx) + "," + (gridY + dy);
                    List<Element> candidates = spatialGrid.getOrDefault(key, new ArrayList<>());

                    // 只检查子弹类对象
                    for (Element bullet : candidates) {
                        if (!(bullet instanceof Shot)) continue;
                        Shot s = (Shot) bullet;

                        // 团队检查 + 防自伤 + 碰撞检测
                        if (s.tank.team != t.team
                                && s.tank != t
                                && s.distance(t) < 20.0) {

                            // 造成伤害
                            t.damage(s.damage);
                            s.destroy();

                            // 统计蓝方被击毁
                            if (t.Destroyed && t.team == TankTeam.BLUE.ordinal()) {
                                this.increaseDemagetanks();
                            }
                        }
                    }
                }
            }
        }
    }


    @Override
    public String toString() {
        return "WarData:{"+"elements"+elements.size();
    }
    public WarData deepCopy() {
        WarData copy = new WarData();
        copy.elements = new CopyOnWriteArrayList<>(this.elements); // 浅拷贝列表
        // 深拷贝每个元素（假设Element实现了Serializable）
        copy.elements = this.elements.stream()
                .map(element -> {
                    try {
                        // 通过序列化实现深拷贝
                        ByteArrayOutputStream bos = new ByteArrayOutputStream();
                        ObjectOutputStream oos = new ObjectOutputStream(bos);
                        oos.writeObject(element);
                        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
                        ObjectInputStream ois = new ObjectInputStream(bis);
                        return (Element) ois.readObject();
                    } catch (Exception e) {
                        throw new RuntimeException("深拷贝失败", e);
                    }
                })
                .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
        return copy;
    }
}